package com.example.animations.activities;

import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.example.animations.R;

public class GeometryEffectActivity extends AppCompatActivity {
    private final String PROGRESS_KEY = "PROGRESS_KEY";
    private final String POSITION_X_KEY = "POSITION_X_KEY";
    private final String POSITION_Y_KEY = "POSITION_Y_KEY";
    private ImageView _animatableImage;
    private ViewGroup.LayoutParams _params;
    private RelativeLayout _parentLayout;
    private float _minImageSize;
    private float _maxImageSize;
    private Position _position;
    private float _maxX;
    private float _maxY;
    private float _lastX;
    private float _lastY;
    private float _lastProgress;
    private ValueAnimator _animator;
    private PropertyValuesHolder _progressHolder;
    private PropertyValuesHolder _positionXHolder;
    private PropertyValuesHolder _positionYHolder;

    private Button _topLeftButton;
    private Button _topRightButton;
    private Button _bottomRightButton;
    private Button _bottomLeftButton;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_geometry_effect);

        _animatableImage = findViewById(R.id.animatable_image);
        _params = _animatableImage.getLayoutParams();
        _parentLayout = findViewById(R.id.parent_layout);

        _progressHolder = PropertyValuesHolder.ofFloat(PROGRESS_KEY, 0f, 2f);
        _positionXHolder = PropertyValuesHolder.ofFloat(POSITION_X_KEY, 0f, 0f);
        _positionYHolder = PropertyValuesHolder.ofFloat(POSITION_Y_KEY, 0f, 0f);

        _animator = ValueAnimator.ofPropertyValuesHolder(_progressHolder, _positionXHolder, _positionYHolder);

        _animator.addUpdateListener(this::onAnimate);
        _animator.setDuration(800);

        _topLeftButton = findViewById(R.id.top_left_button);
        _topLeftButton.setOnClickListener(l -> setPosition(Position.TOP_LEFT));
        _topRightButton = findViewById(R.id.top_right_button);
        _topRightButton.setOnClickListener(l -> setPosition(Position.TOP_RIGHT));
        _bottomRightButton = findViewById(R.id.bottom_right_button);
        _bottomRightButton.setOnClickListener(l -> setPosition(Position.BOTTOM_RIGHT));
        _bottomLeftButton = findViewById(R.id.bottom_left_button);
        _bottomLeftButton.setOnClickListener(l -> setPosition(Position.BOTTOM_LEFT));
    }

    private void onAnimate(ValueAnimator valueAnimator) {
        _lastProgress = ((Number) valueAnimator.getAnimatedValue(PROGRESS_KEY)).floatValue();
        float size = _minImageSize + (_maxImageSize - _minImageSize) * (1 - Math.abs(1 - _lastProgress));
        int s = ((Number) size).intValue();

        _lastX = ((Number) valueAnimator.getAnimatedValue(POSITION_X_KEY)).floatValue();
        _lastY = ((Number) valueAnimator.getAnimatedValue(POSITION_Y_KEY)).floatValue();

        _animatableImage.setTranslationX(_lastX);
        _animatableImage.setTranslationY(_lastY);

        _params.width = s;
        _params.height = s;
        _animatableImage.requestLayout();
    }

    private void setPosition(Position position) {
        if (_position == position) return;

        _position = position;

        if (_minImageSize == 0) {
            _minImageSize = _animatableImage.getMeasuredWidth();
            _maxImageSize = _minImageSize * 1.5f;
        }

        if (_maxX == 0 || _maxY == 0) {
            _maxX = _parentLayout.getMeasuredWidth() - _minImageSize;
            _maxY = _parentLayout.getMeasuredHeight() - _minImageSize;
        }

        float destinationX;
        float destinationY;

        _topLeftButton.setEnabled(position != Position.TOP_LEFT);
        _topRightButton.setEnabled(position != Position.TOP_RIGHT);
        _bottomRightButton.setEnabled(position != Position.BOTTOM_RIGHT);
        _bottomLeftButton.setEnabled(position != Position.BOTTOM_LEFT);

        switch (position) {
            case TOP_RIGHT:
                destinationX = _maxX;
                destinationY = 0;
                break;
            case BOTTOM_RIGHT:
                destinationX = _maxX;
                destinationY = _maxY;
                break;
            case BOTTOM_LEFT:
                destinationX = 0;
                destinationY = _maxY;
                break;
            case TOP_LEFT:
            default:
                destinationX = 0;
                destinationY = 0;
                break;
        }

        _positionXHolder.setFloatValues(_lastX, destinationX);
        _positionYHolder.setFloatValues(_lastY, destinationY);
        _progressHolder.setFloatValues(_lastProgress, _lastProgress > 0 ? 0f : 2f);

        _animator.start();
    }

    private enum Position {
        TOP_LEFT,
        TOP_RIGHT,
        BOTTOM_RIGHT,
        BOTTOM_LEFT
    }
}
